package com.aishua.fire.config.jwtsecurity.res;

import java.util.ArrayList;
import java.util.Collection;
//import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Service;

import com.aishua.fire.common.RequestLogUtil;
import com.aishua.fire.common.constant.DictConstants;
import com.aishua.fire.common.constant.PermInitConstants;
import com.aishua.fire.common.constant.SessionConstants;
import com.aishua.fire.config.init.Init;
import com.aishua.fire.config.init.PermInfo;

import org.springframework.security.web.FilterInvocation;

import lombok.extern.slf4j.Slf4j;

/**
 * 此类为未完成的类
 * @author Administrator
 *
 */
@Slf4j
@Service
public class MyInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

	@Autowired
	private RequestLogUtil logUtil;
	

	//此方法是为了判定用户请求的url 是否在权限表中，如果在权限表中，则返回给 decide 方法，用来判定用户是否有此权限。如果不在权限表中则放行。
    //因为我不想每一次来了请求，都先要匹配一下权限表中的信息是不是包含此url，
    // 我准备直接拦截，不管请求的url 是什么都直接拦截，然后在MyAccessDecisionManager的decide 方法中做拦截还是放行的决策。
    //所以此方法的返回值不能返回 null 此处我就随便返回一下。
	@Override
	public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
		HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
		//String url = ((FilterInvocation) object).getRequestUrl();
		String uri = request.getRequestURI();
		String method = request.getMethod();
//		log.info("请求的uri is :{}" , uri);
//		log.info("当前的请求方法 :{}" , method);
		synchronized (Init.class) {
			ConcurrentHashMap<PermInfo, Collection<ConfigAttribute>> resourceMap = Init.getUrlMap();
	       // return resourceMap.get(uri+method);
	        for(Map.Entry<PermInfo, Collection<ConfigAttribute>> entry : resourceMap.entrySet()) {
	        	PermInfo perm = entry.getKey();
	        	if(perm.getRequestMethod().equalsIgnoreCase(method)) {
	        		String regex = perm.getPermName();
	        		//log.info("regex值是:{}",regex);
	        		//log.info("uri值是:{}",uri);
	        		if(Pattern.matches(regex, uri)) {
	        			Collection<ConfigAttribute> values = entry.getValue();
	        			log.info("返回的数据集是:{},perm信息是:{}",values,perm);
	        			
	        			
	        			//直接放行的接口
	        			if(DictConstants.NO_VALIDATE_YES.equals(perm.getNoValidate())) {
	        				values.clear();
	        				ConfigAttribute configAttribute = new SecurityConfig(PermInitConstants.NO_VALIDATE_PERM);  
	        				values.add(configAttribute);
	        				return values;
	        			}
	        			
	        			//默认只有登录权限,放行的接口
	        			if(DictConstants.ISBLANK_PERM_YES.equals(perm.getIsBlank())) {
	        				values.clear();
	        				ConfigAttribute configAttribute = new SecurityConfig(PermInitConstants.Only_login);  
	        	            values.add(configAttribute);
	        	            return values;
	        			}
	        			
	        			
	        			//插入请求逻辑,并添加幂等性校验
	        			String userName = (String) request.getAttribute(SessionConstants.JWT_USERNAME);
	        			//添加请求处理日志
	        			logUtil.processRequestLog(request, userName,perm);
	        			
	        			//添加默认数据
	        			if(values.size()<1){  
	        	            ConfigAttribute configAttribute = new SecurityConfig("ROLE_NO_USER");  
	        	            values.add(configAttribute);  
	        	        }
	        			return values;
	        		}
	        	}
	        }
		}
        
        //添加默认数据
        Collection<ConfigAttribute> values = new ArrayList<ConfigAttribute>();
        ConfigAttribute configAttribute = new SecurityConfig("ROLE_NO_USER2");  
        values.add(configAttribute);
        return values;
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}


}
